using System;
using System.Collections;
using System.Runtime.Serialization;
using System.Windows.Forms;

using FreeFlow.WinFormsControls.HelperClasses;

namespace FreeFlowAdministrator
{
  /// <summary>
  /// Summary description for TreeNodeFactory.
  /// </summary>
  public sealed class TreeNodeFactory
  {
    private TreeNodeFactory()
    {
    }

    public static TreeNode CreateTreeNode(Adaptor adaptor)
    {
      AdaptorTreeNode node = new AdaptorTreeNode(adaptor.Text);
      node.ImageIndex = adaptor.ImageIndex;
      node.SelectedImageIndex = adaptor.ImageIndex;
      node.Tag = adaptor;
      adaptor.ItemAdded += new EventHandler(node.AdaptorAdded);
      adaptor.ItemDeleted += new EventHandler(node.AdaptorDeleted);
      adaptor.RefreshRequired +=new EventHandler(node.RefreshRequired);
      return node;
    }
  }

  [Serializable]
  public class AdaptorTreeNode : TreeNode
  {
    protected AdaptorTreeNode(SerializationInfo info, StreamingContext context)
      : base(info, context)
    {
    }

    public AdaptorTreeNode(string text) : base(text)
    {
    }

    public void RemoveAndRefreshParent()
    {
      using (new CursorHandler())
      {
        // refresh the parent node's text
        if ((Parent != null) && (Parent.Tag is Adaptor) && (Tag is Adaptor))
        {
          object deletedObject = ((Adaptor)Tag).Object;
          Adaptor adaptor = (Adaptor)Parent.Tag;
          if (adaptor.Object is IList)
            ((IList)adaptor.Object).Remove(deletedObject);
          Parent.Text = adaptor.Text;
        }
        TreeView.Nodes.Remove(this);
      }
    }

    internal void AdaptorDeleted(object sender, EventArgs e)
    {
      RemoveAndRefreshParent();
    }

    private void RefreshChildren()
    {
      TreeView.BeginUpdate();
      try
      {
        if (Tag is Adaptor)
        {
          Adaptor adaptor = ((Adaptor)Tag);
          Text = adaptor.Text;
          Nodes.Clear();
          adaptor.AddChildren(this);
        }
      }
      finally
      {
        TreeView.EndUpdate();
      }
    }

    internal void RefreshRequired(object sender, EventArgs e)
    {
      RefreshChildren();
    }

    internal void AdaptorAdded(object sender, EventArgs e)
    {
      RefreshChildren();

      // assume the added node is at the end - true for users, may not be true if used elsewhere
      TreeView.SelectedNode = Nodes[Nodes.Count-1];
    }
  }
}
